/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.annotation.AliasFor;
import org.springframework.core.type.filter.TypeFilter;

/**
 * Configures component scanning directives for use with @{@link Configuration} classes.
 * Provides support parallel with Spring XML's {@code <context:component-scan>} element.
 *
 * <p>Either {@link #basePackageClasses} or {@link #basePackages} (or its alias
 * {@link #value}) may be specified to define specific packages to scan. If specific
 * packages are not defined, scanning will occur from the package of the
 * class that declares this annotation.
 *
 * <p>Note that the {@code <context:component-scan>} element has an
 * {@code annotation-config} attribute; however, this annotation does not. This is because
 * in almost all cases when using {@code @ComponentScan}, default annotation config
 * processing (e.g. processing {@code @Autowired} and friends) is assumed. Furthermore,
 * when using {@link AnnotationConfigApplicationContext}, annotation config processors are
 * always registered, meaning that any attempt to disable them at the
 * {@code @ComponentScan} level would be ignored.
 *
 * <p>See {@link Configuration @Configuration}'s Javadoc for usage examples.
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @author Sam Brannen
 * @since 3.1
 * @see Configuration
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {

	/**
	 * Alias for {@link #basePackages}.
	 * <p>Allows for more concise annotation declarations if no other attributes
	 * are needed &mdash; for example, {@code @ComponentScan("org.my.pkg")}
	 * instead of {@code @ComponentScan(basePackages = "org.my.pkg")}.
	 */
	@AliasFor("basePackages")
	String[] value() default {};

	/**
	 * Base packages to scan for annotated components.
	 * <p>{@link #value} is an alias for (and mutually exclusive with) this
	 * attribute.
	 * <p>Use {@link #basePackageClasses} for a type-safe alternative to
	 * String-based package names.
	 *
	 *用于指定组件扫描的基础包路径
	 */
	@AliasFor("value")
	String[] basePackages() default {};

	/**
	 * Type-safe alternative to {@link #basePackages} for specifying the packages
	 * to scan for annotated components. The package of each class specified will be scanned.
	 * <p>Consider creating a special no-op marker class or interface in each package
	 * that serves no purpose other than being referenced by this attribute.
	 *
	 * 用于指定组件扫描的起始包的另一种方式。它不是直接指定包路径的字符串，而是通过一个或多个类来确定扫描的起始包。
	 * Spring 会将这些指定类所在的包作为扫描的基础包，然后扫描这些包及其子包中的组件。
	 */
	Class<?>[] basePackageClasses() default {};

	/**
	 * The {@link BeanNameGenerator} class to be used for naming detected components
	 * within the Spring container.
	 * <p>The default value of the {@link BeanNameGenerator} interface itself indicates
	 * that the scanner used to process this {@code @ComponentScan} annotation should
	 * use its inherited bean name generator, e.g. the default
	 * {@link AnnotationBeanNameGenerator} or any custom instance supplied to the
	 * application context at bootstrap time.
	 * @see AnnotationConfigApplicationContext#setBeanNameGenerator(BeanNameGenerator)
	 * @see AnnotationBeanNameGenerator
	 * @see FullyQualifiedAnnotationBeanNameGenerator
	 *
	 * 名称生成器
	 * 这个名称生成器主要用于为通过组件扫描发现的 Bean 生成名称。在 Spring 容器中，每个 Bean 都有一个名称，用于在容器内部进行标识和引用，
	 * nameGenerator属性提供了一种灵活的方式来控制这些 Bean 名称的生成方式。
	 */
	Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

	/**
	 * The {@link ScopeMetadataResolver} to be used for resolving the scope of detected components.
	 *
	 * 用于指定一个自定义的作用域解析器
	 * 作用域解析器的主要职责是确定在组件扫描过程中发现的@Component（或其派生注解标记）的类的作用域。
	 * 通常情况下，Spring 有默认的作用域解析方式。对于大多数被扫描的组件，如果没有特殊指定，默认作用域是singleton。
	 * 这意味着在整个 Spring 容器的生命周期内，只会有一个该组件的实例存在。例如，当扫描到一个@Service注解标记的业务逻辑类时，
	 * 在没有其他配置的情况下，它会被解析为singleton作用域。
	 */
	Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

	/**
	 * Controls the class files eligible for component detection.
	 * <p>Consider use of {@link #includeFilters} and {@link #excludeFilters}
	 * for a more flexible approach.
	 *
	 * 用于指定在组件扫描过程中，Spring 应该查找类文件的资源模式。它主要涉及到 Spring 如何在指定的包路径下（通过basePackages
	 * 或basePackageClasses属性定义）搜索带有@Component及其派生注解（如@Service、@Repository、@Controller）的类文件。
	 */
	//Spring 在进行组件扫描时，默认的资源模式是**/*.class。这意味着它会在指定的包及其子包下查找所有以.class为后缀的文件。
	//这种模式能够满足大多数情况下的组件扫描需求，因为在 Java 项目中，编译后的类文件都带有.class后缀，并且通常是按照包结构存储在文件系统中。
	String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;

	/**
	 * Indicates whether proxies should be generated for detected components, which may be
	 * necessary when using scopes in a proxy-style fashion.
	 * <p>The default is defer to the default behavior of the component scanner used to
	 * execute the actual scan.
	 * <p>Note that setting this attribute overrides any value set for {@link #scopeResolver}.
	 * @see ClassPathBeanDefinitionScanner#setScopedProxyMode(ScopedProxyMode)
	 *
	 *
	 * ScopedProxy用于处理具有特定作用域（Scope）的组件的代理（Proxy）相关设置。当一个组件被定义为具有某种特定的非单例作用域（如请求作用域、会话作用域等）时，
	 * ScopedProxy可以控制 Spring 是否为这个组件创建一个代理对象，以及如何创建这个代理对象。
	 */
	ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

	/**
	 * Indicates whether automatic detection of classes annotated with {@code @Component}
	 * {@code @Repository}, {@code @Service}, or {@code @Controller} should be enabled.
	 *
	 * 用于控制是否使用默认的过滤器来扫描组件
	 * 当useDefaultFilters属性值为true（默认值）时，@ComponentScan会使用默认的过滤器来扫描组件。默认过滤器会扫描带有@Component、
	 * @Repository、@Service、@Controller这些注解的类。这些注解都是@Component注解的派生注解，它们在语义上用于标记不同类型的组件，
	 * 比如@Repository用于标记数据访问层的组件，@Service用于标记业务逻辑层的组件，@Controller用于标记 Web 层的控制器组件。
	 * 这种默认过滤机制使得 Spring 能够自动发现和注册应用程序中的各种组件，将它们作为 Spring 容器中的 Bean 进行管理。
	 * 例如，在一个典型的 Spring MVC 应用中，@Controller注解的类会被扫描并注册为处理 HTTP 请求的 Bean，
	 * @Service注解的类会被注册为包含业务逻辑的 Bean，@Repository注解的类会被注册为执行数据访问操作的 Bean。
	 *
	 * 当useDefaultFilters属性值被设置为false时，@ComponentScan将不会使用上述默认过滤器。这意味着如果希望扫描特定的自定义注解标记的类，
	 * 或者只想扫描没有任何特定注解但满足其他条件（如实现了某个接口、位于特定的包路径等）的类时，就可以将useDefaultFilters设置为false，
	 * 然后通过@ComponentScan的includeFilters和excludeFilters属性来手动配置过滤器。
	 * 例如，假设开发了一个自定义注解@MyCustomComponent，并且只想扫描带有这个注解的类。可以将useDefaultFilters设置为false，
	 * 然后使用includeFilters添加一个AnnotationTypeFilter来指定只扫描带有@MyCustomComponent注解的类。
	 * 如下所示：
	 * @ComponentScan(basePackages = "com.example.demo", useDefaultFilters = false,
 	 * includeFilters = @Filter(type = FilterType.ANNOTATION, value = MyCustomComponent.class))
	 * 这样，`@ComponentScan`就会按照自定义的过滤规则进行组件扫描，而忽略默认的扫描规则。这种方式提供了更灵活的组件扫描机制，能够满足各种特殊的组件扫描需求。
	 */
	boolean useDefaultFilters() default true;

	/**
	 * Specifies which types are eligible for component scanning.
	 * <p>Further narrows the set of candidate components from everything in {@link #basePackages}
	 * to everything in the base packages that matches the given filter or filters.
	 * <p>Note that these filters will be applied in addition to the default filters, if specified.
	 * Any type under the specified base packages which matches a given filter will be included,
	 * even if it does not match the default filters (i.e. is not annotated with {@code @Component}).
	 * @see #resourcePattern()
	 * @see #useDefaultFilters()
	 *
	 * 主要用于自定义组件扫描时的包含规则。它允许你精确地指定哪些组件应该被包含在扫描范围内，从而打破默认的扫描所有@Component及其派生注解
	 * （如@Service、@Repository、@Controller）标注的类的方式。
	 */
	Filter[] includeFilters() default {};

	/**
	 * Specifies which types are not eligible for component scanning.
	 * @see #resourcePattern
	 *
	 * 主要用于在组件扫描过程中排除特定的类，使其不被注册为 Spring 容器中的 Bean。这为开发者提供了一种灵活的方式来精确控制哪些组件不应该被纳入 Spring 的管理范围，
	 * 尤其在处理复杂的项目结构或存在特殊需求的场景下非常有用。
	 */
	Filter[] excludeFilters() default {};

	/**
	 * Specify whether scanned beans should be registered for lazy initialization.
	 * <p>Default is {@code false}; switch this to {@code true} when desired.
	 * @since 4.1
	 */
	boolean lazyInit() default false;


	/**
	 * Declares the type filter to be used as an {@linkplain ComponentScan#includeFilters
	 * include filter} or {@linkplain ComponentScan#excludeFilters exclude filter}.
	 */
	@Retention(RetentionPolicy.RUNTIME)
	@Target({})
	@interface Filter {

		/**
		 * The type of filter to use.
		 * <p>Default is {@link FilterType#ANNOTATION}.
		 * @see #classes
		 * @see #pattern
		 */
		FilterType type() default FilterType.ANNOTATION;

		/**
		 * Alias for {@link #classes}.
		 * @see #classes
		 */
		@AliasFor("classes")
		Class<?>[] value() default {};

		/**
		 * The class or classes to use as the filter.
		 * <p>The following table explains how the classes will be interpreted
		 * based on the configured value of the {@link #type} attribute.
		 * <table border="1">
		 * <tr><th>{@code FilterType}</th><th>Class Interpreted As</th></tr>
		 * <tr><td>{@link FilterType#ANNOTATION ANNOTATION}</td>
		 * <td>the annotation itself</td></tr>
		 * <tr><td>{@link FilterType#ASSIGNABLE_TYPE ASSIGNABLE_TYPE}</td>
		 * <td>the type that detected components should be assignable to</td></tr>
		 * <tr><td>{@link FilterType#CUSTOM CUSTOM}</td>
		 * <td>an implementation of {@link TypeFilter}</td></tr>
		 * </table>
		 * <p>When multiple classes are specified, <em>OR</em> logic is applied
		 * &mdash; for example, "include types annotated with {@code @Foo} OR {@code @Bar}".
		 * <p>Custom {@link TypeFilter TypeFilters} may optionally implement any of the
		 * following {@link org.springframework.beans.factory.Aware Aware} interfaces, and
		 * their respective methods will be called prior to {@link TypeFilter#match match}:
		 * <ul>
		 * <li>{@link org.springframework.context.EnvironmentAware EnvironmentAware}</li>
		 * <li>{@link org.springframework.beans.factory.BeanFactoryAware BeanFactoryAware}
		 * <li>{@link org.springframework.beans.factory.BeanClassLoaderAware BeanClassLoaderAware}
		 * <li>{@link org.springframework.context.ResourceLoaderAware ResourceLoaderAware}
		 * </ul>
		 * <p>Specifying zero classes is permitted but will have no effect on component
		 * scanning.
		 * @since 4.2
		 * @see #value
		 * @see #type
		 */
		@AliasFor("value")
		Class<?>[] classes() default {};

		/**
		 * The pattern (or patterns) to use for the filter, as an alternative
		 * to specifying a Class {@link #value}.
		 * <p>If {@link #type} is set to {@link FilterType#ASPECTJ ASPECTJ},
		 * this is an AspectJ type pattern expression. If {@link #type} is
		 * set to {@link FilterType#REGEX REGEX}, this is a regex pattern
		 * for the fully-qualified class names to match.
		 * @see #type
		 * @see #classes
		 */
		String[] pattern() default {};

	}

}
